package inglar.autotc.client;

import inglar.autotc.client.ui.NodeClass;
import inglar.autotc.client.ui.NodeFilter;
import inglar.autotc.client.ui.NodeQDisc;

import java.util.HashMap;

import com.google.gwt.user.client.ui.Composite;
import com.google.gwt.user.client.ui.Tree;
import com.google.gwt.user.client.ui.TreeItem;

/**
 * A reference for attaching qdiscs, classes, and filters to nodes.
 * @author Lee
 */
public class NodeLookup {
	
	HashMap<String, TreeItem> reference = new HashMap<String, TreeItem>();
	
	/**
	 * Fetches a {@link TreeItem} object where the given {@link Composite} object will be placed.
	 * @param tree a {@link Tree} node where a {@link Tree} object for <b>component</b> will be looked for.
	 * @param composite a {@link Composite} object; only accepted values are {@link NodeQDisc}, {@link NodeClass} and {@link NodeFilter} objects.
	 * @return a {@link TreeItem} object where <b>component</b> is to be added, or {@code null} if the node's parent is the root of the tree.
	 * @throws IllegalArgumentException  
	 */
	public static TreeItem getParent(Tree tree, Composite composite) throws IllegalArgumentException {
		String parent = "";
		
		if(tree == null) throw new IllegalArgumentException("Argument 1 (TreeItem treeItem) is null");
		if(composite == null) throw new IllegalArgumentException("Argument 2 (Composite composite) is null");
		if(composite instanceof NodeQDisc) {
			NodeQDisc node = (NodeQDisc) composite;
			parent = node.getParentId();
		} else if(composite instanceof NodeClass) { 
			// must not happen!
			if(tree.getItemCount() == 0) throw new IllegalArgumentException("Cannot attach NodeClass object to tree containing no objects");
			NodeClass node = (NodeClass) composite;
			parent = node.getParentId();
		} else if(composite instanceof NodeFilter) {
			if(tree.getItemCount() == 0) throw new IllegalArgumentException("Cannot attach NodeFilter object to tree containing no objects");
			NodeFilter node = (NodeFilter) composite;
			parent = node.getParentId();
		} else {
			String errmsg = "Cannot handle component, instance of " + composite.getClass();
			throw new IllegalArgumentException(errmsg);
		}
		
		int items = 0;
		
		items = tree.getItemCount();
		if(items == 0) return null;
		
		TreeItem temp = tree.getItem(0); // get QDisc at root
		
		return _fork(temp, parent);
		
//		return temp;
	}
	
	/**
	 * Depth-first search a tree.
	 * @param treeItem
	 * @return
	 */
	private static TreeItem _fork(TreeItem treeItem, String tag) {
		Object curr = treeItem.getWidget();
		String name = "";
		if(curr instanceof NodeQDisc) {
			NodeQDisc temp = (NodeQDisc) curr;
			name = temp.getHandle().trim();
			String ti_major = getMajor(name), ti_minor = getMinor(name), 
					tag_major = getMajor(tag), tag_minor = getMinor(tag);
			if((ti_major.equals(tag_major)) && (ti_minor.equals(tag_minor))) return treeItem;
		} else if(curr instanceof NodeClass) {
			NodeClass temp = (NodeClass) curr;
			name = temp.getClassid().trim();
			String ti_major = getMajor(name), ti_minor = getMinor(name), 
					tag_major = getMajor(tag), tag_minor = getMinor(tag);
			if((ti_major.equals(tag_major)) && (ti_minor.equals(tag_minor))) return treeItem;
		} else if(curr instanceof NodeFilter) {
			return null; // must not happen!
		} else {
			throw new IllegalArgumentException("Argument TreeItem object has an unsupported child of class " + curr.getClass().toString());
		}
		
		int ccount = treeItem.getChildCount();
		TreeItem retval = null;
		for(int i = 0; i < ccount; i++) {
			retval = _fork(treeItem.getChild(i), tag);
			if(retval == null) continue;
			else return retval;
		}
		
		return retval;
	}
	
	public static boolean canAdd() {
		
		return false;
	}
	
//	/**
//	 * Depth-first search a {@link TreeItem} object containing {@link NodeQDisc}, {@link NodeClass} and {@link NodeFilter} objects.
//	 * The algorithm will return objects that matches {@link NodeQDisc#getHandle()}, {@link NodeClass#getClassid()}, or {@link NodeFilter#get} 
//	 * @param treeItem the {@link TreeItem} object
//	 * @param tag the matching criteria
//	 * @return
//	 */
//	public static TreeItem getTreeItem(TreeItem treeItem, String tag) {
//		
//		return null;
//	}
	
//	public static interface HasParentId {
//		String getParentId();
//	}
	
	public static String getMajor(String tag) {
		int colon = tag.indexOf(':');
		if(colon < 1) return ""; //throw new IllegalArgumentException("Argument tag is invalid");
		return tag.substring(0, colon).trim();
//		return null;
	}
	
	public static String getMinor(String tag) {
		int colon = tag.indexOf(':');
		if(colon < 1) return "";//throw new IllegalArgumentException("Argument tag is invalid");
		String temp = tag.substring(colon + 1).trim();
		if(temp.isEmpty()) return "0";
		else {
			int retval = Integer.parseInt(temp);
			return retval + "";
		}
//		return null;
	}
	
}
